Hadoop指导文档安装配置虚拟机安装 jdk hadoop 等软件Hadoop单机版/伪分布式版单机版运行伪分布式版配置和启动伪分布式版实例运行Hadoop全分布式版基础网络配置无密码登录节点分布式环境配置分布式版 Hadoop 启动分布式版实例运行编写 Hadoop 应用Eclipse中编写 Hadoop 应用命令行下编译运行hadoop应用附录无密码登录配置Virtualbox 的说明
- By 信息科学技术学院 郑力 冯存光
- 文档如有错误或建议,烦请联系助教
按 PPT 上安装好虚拟机和 ubuntu 18.04 LTS 并启动。
将软件源替换为 TUNA 的软件源镜像 ,加快软件下载速度
Ubuntu 的软件源配置文件是 /etc/apt/sources.list
sudo gedit /etc/apt/sources.list然后将该文件内容替换为下面内容,ctrl s 保存。
x# 默认注释了源码镜像以提高 apt update 速度,如有需要可自行取消注释deb https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ bionic main restricted universe multiverse# deb-src https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ bionic main restricted universe multiversedeb https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ bionic-updates main restricted universe multiverse# deb-src https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ bionic-updates main restricted universe multiversedeb https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ bionic-backports main restricted universe multiverse# deb-src https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ bionic-backports main restricted universe multiversedeb https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ bionic-security main restricted universe multiverse# deb-src https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ bionic-security main restricted universe multiverse# 预发布软件源,不建议启用# deb https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ bionic-proposed main restricted universe multiverse# deb-src https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ bionic-proposed main restricted universe multiverse
安装 jdk8
xxxxxxxxxxsudo apt update #更新软件源的metadatasudo apt install openjdk-8-jdk-headlesssudo apt install net-tools openssh-server配置环境变量
xxxxxxxxxxgedit ~/.bashrc在文件末另起一行添加如下内容,并保存
xxxxxxxxxxexport JAVA_HOME=/usr/lib/jvm/java-8-openjdk-amd64/运行命令 source ~/.bashrc 使之生效。
然后我们下载hadoop,并解压到 /usr/local/hadoop/ ,最后修改权限:
xxxxxxxxxxcd ~/Downloadswget "https://mirrors.tuna.tsinghua.edu.cn/apache/hadoop/common/hadoop-2.7.7/hadoop-2.7.7.tar.gz"sudo mkdir /usr/local/hadoopsudo tar xzf hadoop-2.7.7.tar.gz -C /usr/local/hadoopsudo chmod -R 755 /usr/local/hadoop/hadoop-2.7.7sudo chown -R alice:alice /usr/local/hadoop/hadoop-2.7.7运行一下hadoop看版本信息
xxxxxxxxxx/usr/local/hadoop/hadoop-2.7.7/bin/hadoop version为了方便以后每次运行hadoop都不用写这么长的路径,配置一下环境变量,在~/.bashrc文件末加上如下内容并保存。
xxxxxxxxxxexport HADOOP_HOME=/usr/local/hadoop/hadoop-2.7.7export PATH=$PATH:$HADOOP_HOME/sbinexport PATH=$PATH:$HADOOP_HOME/bin然后运行命令 source ~/.bashrc 使之生效。当我们再次运行 /usr/local/hadoop/hadoop-2.7.7/sbin 和 /usr/local/hadoop/hadoop-2.7.7/sbin 目录下的程序的时候,不用再长长的输入绝对路径:
Hadoop默认即为单机版。
xxxxxxxxxx cd /usr/local/hadoop/hadoop-2.7.7 mkdir ./input cp ./etc/hadoop/*.xml ./input # 将配置文件作为输入文件 hadoop jar share/hadoop/mapreduce/hadoop-mapreduce-examples-2.7.7.jar grep input output 'dfs[a-z.]+' cat ./output/* # 查看运行结果结果表明符合正则表达式'dfs[a-z.]+'的单词只出现了一次:
Hadoop不会自动覆盖结果文件,如想再运行上述例子需先删除结果
xxxxxxxxxxrm -r ./output尝试使用 ssh 登陆本机
xxxxxxxxxxssh localhost第一次登陆会有SSH登陆提示,输入yes,并输入用户密码,即可SSH登陆至本机。然后配置SSH无密码登陆:
xxxxxxxxxxexit # 退出刚才的 ssh localhostcd ~/.ssh/ # 若没有该目录,请先执行一次ssh localhostssh-keygen -t rsa # 生成密钥对,会有提示,都按回车就可以cat ./id_rsa.pub >> ./authorized_keys # 加入授权此时再 ssh localhost 即可无密登陆,注意记得exit回原终端。
修改 /usr/local/hadoop/hadoop-2.7.7/etc/hadoop/core-site.xml 配置文件 未修改之前是:
配置改成
xxxxxxxxxx<configuration> <property> <name>hadoop.tmp.dir</name> <value>file:/usr/local/hadoop/hadoop-2.7.7/tmp</value> <description>Abase for other temporary directories.</description> </property> <property> <name>fs.defaultFS</name> <value>hdfs://localhost:9000</value> </property></configuration>然后修改 /usr/local/hadoop/hadoop-2.7.7/etc/hadoop/hdfs-site.xml
xxxxxxxxxx<configuration> <property> <name>dfs.replication</name> <value>1</value> </property> <property> <name>dfs.namenode.name.dir</name> <value>file:/usr/local/hadoop/hadoop-2.7.7/tmp/dfs/name</value> </property> <property> <name>dfs.datanode.data.dir</name> <value>file:/usr/local/hadoop/hadoop-2.7.7/tmp/dfs/data</value> </property></configuration>先别急,运行 gedit etc/hadoop/hadoop-env.sh ,将 export JAVA_HOME=${JAVA_HOME} 改成 export JAVA_HOME=/usr/lib/jvm/java-8-openjdk-amd64
3.执行 NameNode 的格式化:
xxxxxxxxxxhdfs namenode -format
出现“Exitting with status 0” 的提示说明成功。
4.接着开启 NameNode 和 DataNode 守护进程:
xxxxxxxxxxstart-dfs.sh
5.启动完成后,可以通过命令jps来判断是否成功启动,若成功启动则会列出如下进程:
此时打开firefox访问 http://localhost:50070 可以查看 NameNode 和 Datanode 信息,还可以在线查看 HDFS 中的文件。
1.创建目录,并将本地配置文件作为输入复制到分布式系统。
xxxxxxxxxxhdfs dfs -mkdir -p /user/alicehdfs dfs -mkdir inputcd /usr/local/hadoop/hadoop-2.7.7hdfs dfs -put ./etc/hadoop/*.xml input上面最后一条命令执行后,可能会报一个WARN,但是无妨,通过如下命令查看文件是否被传到input文件夹下了
xxxxxxxxxxhdfs dfs -ls input
2.执行实例,并查看结果
xxxxxxxxxxhadoop jar ./share/hadoop/mapreduce/hadoop-mapreduce-examples-*.jar grep input output 'dfs[a-z.]+'hdfs dfs -cat output/*
结果:
3.将结果取回本地
xxxxxxxxxxrm -r ./output # 先删除本地的 output 文件夹(如果存在)hdfs dfs -get output ./output # 将结果拷贝到本机cat ./output/*4.为不影响下次运行,及时删除输出文件
xxxxxxxxxxhdfs dfs -rm -r output
5.关闭hadoop
xxxxxxxxxxstop-dfs.sh
下次开启时无需格式化,仅需命令 start-dfs.sh 即可
请先完成上述单机版/伪分布式版后再进行本版本操作
取消勾选"使用本地DHCP...",填写子网IP为 192.168.8.0 子网掩码为 255.255.255.0
点击NAT设置,填写网关IP为 192.168.8.2 确定。
确保每个虚拟机都是NAT模式以及mac地址互不相同。
右键虚拟机设置,这里可以更改内存等设置。点击网络适配器,确保网络连接是NAT模式。点击高级,查看mac地址,点击生成可以随机生成一个mac地址防止冲突。
Ubuntu网络配置。
本教程中,三节点的Address分别设置为 192.168.8.100/101/102
如果你使用的是 Ubuntu系统上的 VirtualBox,那么请参考文末
xxxxxxxxxxsudo gedit /etc/hostname之后修改/etc/hosts的前几行,如下配置。注意127.0.0.1仅可对应localhost,不可保留有其他对应行。
xxxxxxxxxx127.0.0.1 localhost192.168.8.100 Master192.168.8.101 Slave1192.168.8.102 Slave2
在Slave1、Slave2机上作类似操作,操作后均需重启生效。 在3个虚拟机上分别尝试互相Ping,如果都能ping通则没问题。
xxxxxxxxxxping -c 3 Masterping -c 3 Slave1ping -c 3 Slave2由于Master和Slave都是从伪分布式配置后的虚拟机克隆的,含有一样的密钥对,所以正常情况下能够登陆:
xxxxxxxxxxssh Masterssh Slave1ssh Slave2输入yes回车即可登陆成功,exit退回原来终端后再次ssh即可直接无密登陆。 如果不能成功,请按照文末 无密码登录 配置进行配置。
xxxxxxxxxxcd /usr/local/hadoop/hadoop-2.7.7/etc/hadoopxxxxxxxxxxSlave1Slave2
xxxxxxxxxx<configuration> <property> <name>hadoop.tmp.dir</name> <value>file:/usr/local/hadoop/hadoop-2.7.7/tmp</value> <description>Abase for other temporary directories.</description> </property> <property> <name>fs.defaultFS</name> <value>hdfs://Master:9000</value> </property></configuration>xxxxxxxxxx<configuration> <property> <name>dfs.namenode.secondary.http-address</name> <value>Master:50090</value> </property> <property> <name>dfs.replication</name> <value>2</value> </property> <property> <name>dfs.namenode.name.dir</name> <value>file:/usr/local/hadoop/hadoop-2.7.7/tmp/dfs/name</value> </property> <property> <name>dfs.datanode.data.dir</name> <value>file:/usr/local/hadoop/hadoop-2.7.7/tmp/dfs/data</value> </property></configuration>cp mapred-site.xml.template mapred-site.xml 之后修改内容xxxxxxxxxx<configuration> <property> <name>mapreduce.framework.name</name> <value>yarn</value> </property> <property> <name>mapreduce.jobhistory.address</name> <value>Master:10020</value> </property> <property> <name>mapreduce.jobhistory.webapp.address</name> <value>Master:19888</value> </property></configuration>xxxxxxxxxx<configuration> <property> <name>yarn.resourcemanager.hostname</name> <value>Master</value> </property> <property> <name>yarn.nodemanager.aux-services</name> <value>mapreduce_shuffle</value> </property></configuration>最后我们需要把 Hadoop 从Master 复制到 Slave 节点, 但是由于我们之更改了一些配置文件,所以只需要复制Master的配置文件到Slave节点覆盖就好了。
xxxxxxxxxx#先清理一些临时文件cd /usr/local/hadoop/hadoop-2.7.7;rm -r ./tmp ./logs/*ssh Slave1 "cd /usr/local/hadoop/hadoop-2.7.7;rm -r ./tmp ./logs/*"ssh Slave1 "cd /usr/local/hadoop/hadoop-2.7.7;rm -r ./tmp ./logs/*"#复制Master的配置文件到Slave节点scp /usr/local/hadoop/hadoop-2.7.7/etc/hadoop/* Slave1:/usr/local/hadoop/hadoop-2.7.7/etc/hadoop/scp /usr/local/hadoop/hadoop-2.7.7/etc/hadoop/* Slave2:/usr/local/hadoop/hadoop-2.7.7/etc/hadoop/xxxxxxxxxxhdfs namenode -format
xxxxxxxxxxstart-dfs.shstart-yarn.shmr-jobhistory-daemon.sh start historyserver
通过jps命令可查看进程,在Master上进程如下(五个进程必须全部启动,如有缺失即为启动有错。端口号不一样为正常现象)
在Slave节点上进程如下
另外,在Master上通过命令 hdfs dfsadmin -report 查看节点是否正常启动,若启动成功可在返回的报告中看到:Live datanodes (2)
在firefox中查看网页 http://localhost:50070/dfshealth.html#tab-datanode 也可确定
xxxxxxxxxxhdfs dfs -mkdir -p /user/alice
xxxxxxxxxxhdfs dfs -mkdir inputhdfs dfs -put /usr/local/hadoop/hadoop-2.7.7/etc/hadoop/*.xml inputhdfs dfs -ls input
在网页端可查看节点上的占用情况发生了变化,说明上传成功
xxxxxxxxxxhadoop jar /usr/local/hadoop/hadoop-2.7.7/share/hadoop/mapreduce/hadoop-mapreduce-examples-*.jar grep input output 'dfs[a-z.]+'运行时的输出信息与伪分布式类似,会显示 Job 的进度。 可能会有点慢,若迟迟没有进度(如5分钟),不妨重启Hadoop再试试。若仍不行,则很有可能是内存不足引起,建议增大虚拟机的内存
xxxxxxxxxxhdfs dfs -cat output/*结果如下
xxxxxxxxxxstop-yarn.shstop-dfs.shmr-jobhistory-daemon.sh stop historyserver
使用eclipse编写Java可以方便代码补全和提示。安装eclipse (在Master节点)
xxxxxxxxxxcd Downloadswget "https://mirrors.tuna.tsinghua.edu.cn/eclipse/technology/epp/downloads/release/luna/SR2/eclipse-java-luna-SR2-linux-gtk-x86_64.tar.gz"解压后,双击eclipse文件夹下的eclipse运行
我们来导入hadoop的jar包,菜单栏Window --> Preferences --> Java --> Build Path --> User Libraries --> New 输入 hadoop_common 。
然后选中hadoop_common 添加外部jar,浏览到/usr/local/hadoop/hadoop2.7.7/share/hadoop/common,添加这个目录下的所有.jar文件(按住ctrl多选),然后添加/usr/local/hadoop/hadoop2.7.7/share/hadoop/common/lib下的所有jar包。
按此过程依次添加/usr/local/hadoop/hadoop2.7.7/share/hadoop下的如下jar包:
xxxxxxxxxx新建 hadoop_hdfs 的用户库,然后添加 share\hadoop\hdfs 和 share\hadoop\hdfs\lib 下的jar包新建 hadoop_mapreduce 的用户库,然后添加 share\hadoop\mapreduce 和 share\hadoop\mapreduce\lib 下的jar包
添加完成后:
然后我们新建java工程,
新建过程中加入用户库,不过对于这个简单的例子包含 hadoop_common 和 hadoop_hdfs 就可以了:
建好工程后在src上右键新建类:
确保你的三个虚拟机以及hdfs都处在开启状态。
编写hdfs读写程序样例
xxxxxxxxxximport org.apache.hadoop.conf.Configuration;import org.apache.hadoop.fs.FileSystem;import org.apache.hadoop.fs.Path;import org.apache.hadoop.fs.FSDataOutputStream;import org.apache.hadoop.fs.FSDataInputStream;import java.io.BufferedReader;import java.io.IOException;import java.io.InputStreamReader;public class HDFSWriteRead { public static void main(String[] args){ try{ String fileName = "test"; Configuration conf = new Configuration(); conf.set("fs.defaultFS", "hdfs://Master:9000"); conf.set("fs.hdfs.impl", "org.apache.hadoop.hdfs.DistributedFileSystem"); FileSystem fs = FileSystem.get(conf); Path file = new Path(fileName); if(fs.exists(file)){ System.out.println("File exists"); }else{ System.out.println("File does not exist"); createFile(fs,file); } readFile(fs,file); fs.close(); }catch (Exception e){ e.printStackTrace(); } } public static void createFile(FileSystem fs, Path file) throws IOException{ byte[] buff = "Hello World".getBytes(); FSDataOutputStream os =fs.create(file); os.write(buff,0,buff.length); System.out.println("Create:"+file.getName()); os.close(); } public static void readFile(FileSystem fs, Path file) throws IOException{ FSDataInputStream in = fs.open(file); BufferedReader d = new BufferedReader(new InputStreamReader(in)); String content = d.readLine(); System.out.println(content); d.close(); in.close(); }}该程序的功能是判断名字为test的文件是否存在于hdfs中,如果存在则读取内容,否则先创建再读取。
运行结果如下
现在我们尝试将程序打包运行
xxxxxxxxxxmkdir /usr/local/hadoop-2.7.7/myappFile --> Export --> Runnable JAR File --> Next
进入目录运行hadoop执行该jar包:
如果你使用的是Server版本的Ubuntu,需要在命令行下进行代码编辑和编译。否则不需要。
在~/.bashrc末尾添加
xxxxxxxxxxexport HADOOP_CLASSPATH=$(find $HADOOP_HOME -name '*.jar' | xargs echo | tr ' ' ':')
运行
source ~/.bashrc
然后编译打包运行:
xxxxxxxxxxmkdir buildjavac -classpath ${HADOOP_CLASSPATH} -d build/ HDFSWriteRead.javajar -cvf HDFSWriteRead.jar -C build ./hadoop jar HDFSWriteRead.jar HDFSWriteRead
原理:首先由用户生成一对密钥,然后将公钥保存在SSH服务器用户的目录下.ssh子目录中的authorized_key文件里(/root/.ssh/authorized_key).私钥保存在本地计算机.当用户登陆时,服务器检查authorized_key文件的公钥是否与用户的私钥对应,如果相符则允许登入,否则拒绝.由于私钥只有保存在用户的本地计算机中,因此入侵者就算得到用户口令,也不能登陆到服务器.
在Master机上操作:
xxxxxxxxxxcd ~/.ssh # 如果没有该目录,先执行一次ssh localhostrm ./id_rsa* # 删除之前生成的公匙(如果有)ssh-keygen -t rsa # 生成一对rsa密钥使本机无密SSH本机,键入如下命令
xxxxxxxxxxcat ./id_rsa.pub >> ./authorized_keys完成后尝试ssh Master验证(可能需要输入yes,之后exit退回原终端) 之后将公钥传输至Slave(需要输入节点密码)
xxxxxxxxxxscp ~/.ssh/id_rsa.pub Slave1:~/scp ~/.ssh/id_rsa.pub Slave2:~/在Slave1、Slave2上操作:
xxxxxxxxxxcat ~/id_rsa.pub >> ~/.ssh/authorized_keysrm ~/id_rsa.pub # 用完就可以删掉了在Master上操作: 尝试是否能够无密登陆子节点
xxxxxxxxxxssh Slave1 #注意exit回原终端ssh Slave2 #注意exit回原终端成功后就可以继续配置分布式环境了
Table Overview of Networking Modes
| Mode | VM→Host | VM←Host | VM1↔VM2 | VM→Net/LAN | VM←Net/LAN |
|---|---|---|---|---|---|
| Host-only | + | + | + | – | – |
| Internal | – | – | + | – | – |
| Bridged | + | + | + | + | + |
| NAT | + | Port forward | – | + | Port forward |
| NAT service( NAT nerwork) | + | Port forward | + | + | Port forward |
如果主机是Ubuntu16.04或18.04,那么配置成NAT service会导致vm无法访问外网,这是一个bug,所以要想即能虚拟机之间互相访问又能访问外网,只能选择Bridged模式,而这样每次开机后ip可能会变,需要经常修改hosts。